#ifndef SIMPLE_LOG_H
#define SIMPLE_LOG_H

#include <chrono>
#include <cstdio>
#include <ctime>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <mutex>
#include <sstream>
#include <string>
#include <thread>

#if defined(_WIN32)
#ifndef NOMINMAX
#define NOMINMAX  // 避免Windows.h定义min/max宏
#endif
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN  // 减少Windows头文件的包含
#endif
#include <direct.h>
#include <io.h>
#include <sys/stat.h>
#include <windows.h>

#define mkdir(path, mode) _mkdir(path)
#define stat              _stat
#elif defined(__linux__) || defined(__APPLE__)
#include <dirent.h>
#include <sys/stat.h>
#include <unistd.h>
#endif

namespace simple_log {

// ===== 颜色 =====
#define SIMPLE_LOG_RESET_COLOR  "\033[0m"
#define SIMPLE_LOG_RED_COLOR    "\033[31m"
#define SIMPLE_LOG_YELLOW_COLOR "\033[33m"
#define SIMPLE_LOG_GREEN_COLOR  "\033[32m"
#define SIMPLE_LOG_WHITE_COLOR  "\033[37m"
#define SIMPLE_LOG_CYAN_COLOR   "\033[36m"

// ===== 日志等级 =====
enum class DebugLevel {
    DEBUG_LEVEL_NONE = 0,
    DEBUG_LEVEL_ERROR,
    DEBUG_LEVEL_WARN,
    DEBUG_LEVEL_INFO,
    DEBUG_LEVEL_DEBUG,
};

// ===== 输出选项 =====
enum class DebugOutputOption {
    SHOW_FILENAME       = (1 << 0),
    SHOW_FUNCNAME       = (1 << 1),
    SHOW_LINE           = (1 << 2),
    SHOW_TIMESTAMP      = (1 << 3),
    SHOW_THREAD_ID      = (1 << 4),
    SHOW_LEVEL_FULL     = (1 << 5),  // 显示完整等级名
    TIMESTAMP_MILLIS    = (1 << 6),  // 时间戳包含毫秒
    ENABLE_AUTOLOG      = (1 << 7),  // 启用自动日志（独立于日志级别）
    ENABLE_FILE_LOG     = (1 << 8),  // 启用文件日志
    ENABLE_AUTO_CLEANUP = (1 << 9),  // 启用自动清理旧日志（默认开启，生产环境可关闭）

    DEFAULT = SHOW_FILENAME | SHOW_FUNCNAME | SHOW_LINE | SHOW_TIMESTAMP | SHOW_LEVEL_FULL,
    ALL     = DEFAULT | TIMESTAMP_MILLIS | SHOW_THREAD_ID
};

class SimpleLogger {
public:
    static SimpleLogger& get_instance()
    {
        static SimpleLogger inst;
        return inst;
    }

    void log(DebugLevel level, const std::string& msg, const std::string& file,
             const std::string& func, int line)
    {
        if (level > current_level_) return;
        std::lock_guard< std::mutex > lock(mtx_);

        std::string core_tag = std::string(get_level_color_(level)) + "[" + get_level_str_(level)
                               + "]" + SIMPLE_LOG_RESET_COLOR;

        std::ostream& out = (level <= DebugLevel::DEBUG_LEVEL_WARN) ? std::cerr : std::cout;

        std::string prefix   = emit_prefix_(core_tag, file, func, line);
        std::string log_line = prefix + ": " + msg;

        // 输出到控制台
        out << log_line << std::endl;

        // 输出到文件（如果启用）
        // 注意：这里直接调用 write_to_file_() 而不是 write_to_file()，
        // 因为当前函数已经持有锁 mtx_，避免重复加锁导致死锁
        if (has_option(DebugOutputOption::ENABLE_FILE_LOG)) {
            write_to_file_(log_line);
        }
    }

    // 设置日志文件路径和保留时间（天数）
    // 如果 filepath 为空，则使用默认路径：可执行文件路径下的 logs/ 文件夹
    // enable_auto_cleanup: 是否启用自动清理旧日志（默认 true，生产环境可设为
    // false）
    void set_log_file(const std::string& filepath = "", int retention_days = 7,
                      bool enable_auto_cleanup = true)
    {
        std::lock_guard< std::mutex > lock(mtx_);

        if (filepath.empty()) {
            // 使用默认路径：可执行文件路径下的 logs/app.log
            std::string exe_dir = get_executable_directory_();
#if defined(_WIN32)
            std::string logs_dir = exe_dir + "\\logs";
            log_file_path_       = logs_dir + "\\app.log";
#else
            std::string logs_dir = exe_dir + "/logs";
            log_file_path_       = logs_dir + "/app.log";
#endif
            // 确保 logs 文件夹存在
            create_directory_(logs_dir);
        } else {
            log_file_path_ = filepath;

            std::string log_dir = get_directory_from_path_(log_file_path_);
            if (!log_dir.empty()) {
                create_directory_(log_dir);
            }
        }

        log_file_index_     = 0;
        log_retention_days_ = retention_days;
        if (log_file_.is_open()) {
            log_file_.close();
        }

        set_output_option(DebugOutputOption::ENABLE_AUTO_CLEANUP, enable_auto_cleanup);

        if (enable_auto_cleanup) {
            cleanup_old_logs_();
        }
    }

    // 写入日志到文件（供 AutoLogger 调用）
    void write_to_file(const std::string& log_line)
    {
        std::lock_guard< std::mutex > lock(mtx_);
        write_to_file_(log_line);
    }

    void       set_debug_level(DebugLevel lv) { current_level_ = lv; }
    DebugLevel get_debug_level() const { return current_level_; }

    void set_output_option(DebugOutputOption opt, bool on)
    {
        if (on)
            options_ |= static_cast< int >(opt);
        else
            options_ &= ~static_cast< int >(opt);
    }

    bool has_option(DebugOutputOption opt) const
    {
        return (options_ & static_cast< int >(opt)) != 0;
    }

    std::string get_timestamp_() const
    {
        auto    now        = std::chrono::system_clock::now();
        auto    now_time_t = std::chrono::system_clock::to_time_t(now);
        std::tm tm;

#if defined(_WIN32)
        localtime_s(&tm, &now_time_t);
#else
        localtime_r(&now_time_t, &tm);
#endif

        std::ostringstream oss;
        oss << std::put_time(&tm, "%Y-%m-%d %H:%M:%S");

        if (has_option(DebugOutputOption::TIMESTAMP_MILLIS)) {
            auto ms = std::chrono::duration_cast< std::chrono::milliseconds >(
                now.time_since_epoch() % std::chrono::seconds(1));
            oss << "." << std::setw(3) << std::setfill('0') << ms.count();
        }
        return oss.str();
    }

    std::string base_name_(const std::string& path) const
    {
        size_t pos = path.find_last_of("/\\");
        return (pos == std::string::npos) ? path : path.substr(pos + 1);
    }

    // 供AutoLogger调用的通用前缀生成函数
    std::string emit_prefix_(const std::string& core_tag, const std::string& file,
                             const std::string& func, int line) const
    {
        std::ostringstream oss;

        if (has_option(DebugOutputOption::SHOW_TIMESTAMP)) {
            oss << "[" << get_timestamp_() << "] ";
        }

        oss << core_tag << " ";

        if (has_option(DebugOutputOption::SHOW_THREAD_ID)) {
            oss << SIMPLE_LOG_CYAN_COLOR << "[TID:" << get_thread_id_() << "]"
                << SIMPLE_LOG_RESET_COLOR << " ";
        }

        if (has_option(DebugOutputOption::SHOW_FILENAME)) {
            oss << "[" << base_name_(file);
        }

        if (has_option(DebugOutputOption::SHOW_FUNCNAME)) {
            oss << (has_option(DebugOutputOption::SHOW_FILENAME) ? ":" : "[") << func;
        }

        if (has_option(DebugOutputOption::SHOW_LINE)) {
            oss << (has_option(DebugOutputOption::SHOW_FILENAME)
                            || has_option(DebugOutputOption::SHOW_FUNCNAME)
                        ? ":"
                        : "[")
                << line;
        }
        oss << "]";
        return oss.str();
    }

    // 析构函数：确保文件流正确关闭
    ~SimpleLogger()
    {
        std::lock_guard< std::mutex > lock(mtx_);
        if (log_file_.is_open()) {
            log_file_.close();
        }
    }

private:
    SimpleLogger()
        : current_level_(DebugLevel::DEBUG_LEVEL_DEBUG),
          options_(static_cast< int >(DebugOutputOption::DEFAULT)), log_file_index_(0),
          log_retention_days_(7)
    {
    }

    std::string get_thread_id_() const
    {
        std::stringstream ss;
        ss << std::this_thread::get_id();
        return ss.str();
    }

    const char* get_level_color_(DebugLevel lv) const
    {
        switch (lv) {
        case DebugLevel::DEBUG_LEVEL_ERROR: return SIMPLE_LOG_RED_COLOR;
        case DebugLevel::DEBUG_LEVEL_WARN: return SIMPLE_LOG_YELLOW_COLOR;
        case DebugLevel::DEBUG_LEVEL_INFO: return SIMPLE_LOG_GREEN_COLOR;
        case DebugLevel::DEBUG_LEVEL_DEBUG: return SIMPLE_LOG_WHITE_COLOR;
        default: return SIMPLE_LOG_WHITE_COLOR;
        }
    }

    const char* get_level_str_(DebugLevel lv) const
    {
        if (has_option(DebugOutputOption::SHOW_LEVEL_FULL)) {
            switch (lv) {
            case DebugLevel::DEBUG_LEVEL_ERROR: return "ERROR";
            case DebugLevel::DEBUG_LEVEL_WARN: return "WARN";
            case DebugLevel::DEBUG_LEVEL_INFO: return "INFO";
            case DebugLevel::DEBUG_LEVEL_DEBUG: return "DEBUG";
            default: return "LOG";
            }
        } else {
            switch (lv) {
            case DebugLevel::DEBUG_LEVEL_ERROR: return "E";
            case DebugLevel::DEBUG_LEVEL_WARN: return "W";
            case DebugLevel::DEBUG_LEVEL_INFO: return "I";
            case DebugLevel::DEBUG_LEVEL_DEBUG: return "D";
            default: return "L";
            }
        }
    }
    void write_to_file_(const std::string& log_line)
    {
        try {
            if (log_file_.is_open()) {
                log_file_.seekp(0, std::ios::end);
                std::streampos file_size = log_file_.tellp();
                if (file_size >= 1024 * 1024) {
                    log_file_.close();
                    log_file_index_++;
                    current_file_timestamp_ = get_timestamp_string_();
                }
            }

            if (!log_file_.is_open()) {
                current_file_timestamp_  = get_timestamp_string_();
                std::string current_file = get_log_filename_with_timestamp_();

                struct stat file_info;
                bool        file_exists    = (stat(current_file.c_str(), &file_info) == 0);
                bool        file_too_large = file_exists && (file_info.st_size >= 1024 * 1024);

                if (log_file_index_ > 0 || file_too_large) {
                    log_file_index_++;
                    current_file_timestamp_ = get_timestamp_string_();
                    current_file            = get_log_filename_with_timestamp_();
                    log_file_.open(current_file, std::ios::out);
                } else {
                    log_file_.open(current_file, std::ios::app);
                }
            }

            if (log_file_.is_open()) {
                std::string clean_line = remove_color_codes_(log_line);
                log_file_ << clean_line << std::endl;
                log_file_.flush();
            }
        }
        catch (...) {
            // 文件操作失败时静默处理，避免影响程序运行
            // 如果文件流处于错误状态，关闭它以便下次重试
            if (log_file_.is_open()) {
                log_file_.close();
            }
        }
    }

    std::string get_log_filename_with_timestamp_() const
    {
        std::string current_file = log_file_path_;

        size_t      last_slash = current_file.find_last_of("/\\");
        std::string dir_path, filename;
        if (last_slash != std::string::npos) {
            dir_path = current_file.substr(0, last_slash + 1);
            filename = current_file.substr(last_slash + 1);
        } else {
            dir_path = "";
            filename = current_file;
        }

        size_t      dot_pos = filename.find_last_of('.');
        std::string base_name, extension;
        if (dot_pos != std::string::npos) {
            base_name = filename.substr(0, dot_pos);
            extension = filename.substr(dot_pos);
        } else {
            base_name = filename;
            extension = "";
        }

        std::string timestamp = current_file_timestamp_;
        std::string new_filename;
        if (log_file_index_ > 0) {
            new_filename =
                base_name + "_" + timestamp + "_" + std::to_string(log_file_index_) + extension;
        } else {
            new_filename = base_name + "_" + timestamp + extension;
        }

        return dir_path + new_filename;
    }

    std::string get_timestamp_string_() const
    {
        auto    now        = std::chrono::system_clock::now();
        auto    now_time_t = std::chrono::system_clock::to_time_t(now);
        std::tm tm;

#if defined(_WIN32)
        localtime_s(&tm, &now_time_t);
#else
        localtime_r(&now_time_t, &tm);
#endif

        std::ostringstream oss;
        oss << std::put_time(&tm, "%Y%m%d_%H%M%S");
        return oss.str();
    }

    std::string get_executable_directory_() const
    {
        try {
#if defined(_WIN32)
            char    path[MAX_PATH];
            HMODULE hModule = NULL;
            GetModuleFileNameA(hModule, path, MAX_PATH);
            std::string exe_path(path);
            size_t      last_slash = exe_path.find_last_of("\\/");
            if (last_slash != std::string::npos) {
                return exe_path.substr(0, last_slash);
            }
            return ".";
#elif defined(__linux__) || defined(__APPLE__)
            char    path[1024];
            ssize_t len = readlink("/proc/self/exe", path, sizeof(path) - 1);
            if (len != -1) {
                path[len] = '\0';
                std::string exe_path(path);
                size_t      last_slash = exe_path.find_last_of("/");
                if (last_slash != std::string::npos) {
                    return exe_path.substr(0, last_slash);
                }
            }
            return ".";
#else
            return ".";
#endif
        }
        catch (...) {
            return ".";
        }
    }

    std::string get_directory_from_path_(const std::string& filepath) const
    {
        size_t last_slash = filepath.find_last_of("/\\");
        if (last_slash != std::string::npos) {
            return filepath.substr(0, last_slash);
        }
        return "";
    }

    void create_directory_(const std::string& dir_path) const
    {
        if (dir_path.empty()) return;

        try {
            struct stat info;
            if (stat(dir_path.c_str(), &info) != 0) {
                std::string parent = get_directory_from_path_(dir_path);
                if (!parent.empty() && parent != dir_path) {
                    create_directory_(parent);
                }
                // mkdir 可能失败（如权限不足），但不影响程序运行
                mkdir(dir_path.c_str(), 0755);
            }
        }
        catch (...) {
            // 目录创建失败时静默处理，后续文件打开会失败但不会崩溃
        }
    }

    void cleanup_old_logs_()
    {
        if (!has_option(DebugOutputOption::ENABLE_AUTO_CLEANUP)) return;

        if (log_file_path_.empty()) return;

        try {
            std::string log_dir = get_directory_from_path_(log_file_path_);
            if (log_dir.empty()) {
                log_dir = ".";
            }

            std::string full_name  = log_file_path_;
            size_t      last_slash = full_name.find_last_of("/\\");
            std::string filename =
                (last_slash != std::string::npos) ? full_name.substr(last_slash + 1) : full_name;

            size_t      dot_pos = filename.find_last_of('.');
            std::string base_name =
                (dot_pos != std::string::npos) ? filename.substr(0, dot_pos) : filename;

            time_t     now_time = time(nullptr);
            struct tm* now_tm   = localtime(&now_time);
            now_tm->tm_hour     = 0;
            now_tm->tm_min      = 0;
            now_tm->tm_sec      = 0;
            time_t today_start  = mktime(now_tm);
            time_t expire_time  = today_start - (24 * 60 * 60 * log_retention_days_);

#if defined(_WIN32)
            std::string      search_pattern = log_dir + "\\" + base_name + "*";
            WIN32_FIND_DATAA find_data;
            HANDLE           hFind = FindFirstFileA(search_pattern.c_str(), &find_data);
            if (hFind != INVALID_HANDLE_VALUE) {
                // 使用 RAII 确保 FindClose 被调用
                struct FindHandleGuard
                {
                    HANDLE handle;
                    FindHandleGuard(HANDLE h) : handle(h) {}
                    ~FindHandleGuard()
                    {
                        if (handle != INVALID_HANDLE_VALUE) FindClose(handle);
                    }
                } guard(hFind);

                do {
                    if (!(find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
                        std::string file_name = find_data.cFileName;
                        std::string full_path = log_dir + "\\" + file_name;

                        FILETIME       ft = find_data.ftLastWriteTime;
                        ULARGE_INTEGER ul;
                        ul.LowPart        = ft.dwLowDateTime;
                        ul.HighPart       = ft.dwHighDateTime;
                        time_t file_mtime = (time_t)(ul.QuadPart / 10000000ULL - 11644473600ULL);

                        struct tm  file_tm_buf;
                        struct tm* file_tm = nullptr;
#if defined(_WIN32)
                        localtime_s(&file_tm_buf, &file_mtime);
                        file_tm = &file_tm_buf;
#else
                        file_tm = localtime(&file_mtime);
#endif
                        file_tm->tm_hour       = 0;
                        file_tm->tm_min        = 0;
                        file_tm->tm_sec        = 0;
                        time_t file_date_start = mktime(file_tm);

                        if (file_date_start < expire_time) {
                            std::remove(full_path.c_str());
                        }
                    }
                } while (FindNextFileA(hFind, &find_data));
                // guard 析构时会自动调用 FindClose
            }
#else
            DIR* dir = opendir(log_dir.c_str());
            if (dir != nullptr) {
                // 使用 RAII 确保 closedir 被调用
                struct DirGuard
                {
                    DIR* dir_ptr;
                    DirGuard(DIR* d) : dir_ptr(d) {}
                    ~DirGuard()
                    {
                        if (dir_ptr != nullptr) closedir(dir_ptr);
                    }
                } guard(dir);

                struct dirent* entry;
                while ((entry = readdir(dir)) != nullptr) {
                    std::string file_name = entry->d_name;

                    if (file_name == "." || file_name == "..") continue;

                    if (file_name.find(base_name) == 0) {
                        std::string full_path = log_dir + "/" + file_name;
                        struct stat file_info;
                        if (stat(full_path.c_str(), &file_info) == 0) {
                            if (S_ISREG(file_info.st_mode)) {
                                time_t file_mtime = file_info.st_mtime;

                                struct tm  file_tm_buf;
                                struct tm* file_tm = localtime_r(&file_mtime, &file_tm_buf);
                                if (file_tm != nullptr) {
                                    file_tm->tm_hour       = 0;
                                    file_tm->tm_min        = 0;
                                    file_tm->tm_sec        = 0;
                                    time_t file_date_start = mktime(file_tm);

                                    if (file_date_start < expire_time) {
                                        std::remove(full_path.c_str());
                                    }
                                }
                            }
                        }
                    }
                }
                // guard 析构时会自动调用 closedir
            }
#endif
        }
        catch (...) {
        }
    }

    std::string remove_color_codes_(const std::string& str) const
    {
        std::string result = str;
        size_t      pos    = 0;
        while ((pos = result.find("\033[", pos)) != std::string::npos) {
            size_t end = result.find('m', pos);
            if (end != std::string::npos) {
                result.erase(pos, end - pos + 1);
            } else {
                break;
            }
        }
        return result;
    }

    DebugLevel current_level_;
    int        options_;
    std::mutex mtx_;

    std::string   log_file_path_;
    std::ofstream log_file_;
    int           log_file_index_;
    int           log_retention_days_;
    std::string   current_file_timestamp_;
};

class LogStream {
public:
    LogStream(DebugLevel lv, const std::string& file, const std::string& func, int line,
              bool condition = true)
        : lv_(lv), file_(file), func_(func), line_(line),
          enabled_(condition && lv <= SimpleLogger::get_instance().get_debug_level())
    {
    }

    template < typename T > LogStream& operator<<(const T& v)
    {
        if (enabled_) oss_ << v;
        return *this;
    }

    ~LogStream()
    {
        if (enabled_) {
            SimpleLogger::get_instance().log(lv_, oss_.str(), file_, func_, line_);
        }
    }

private:
    DebugLevel         lv_;
    std::ostringstream oss_;
    std::string        file_, func_;
    int                line_;
    bool               enabled_;
};

class AutoLogger {
public:
    template < typename... Args >
    AutoLogger(const std::string& file, const std::string& func, int line, Args&&... args)
        : file_(file), func_(func), line_(line)
    {
        auto&      logger = SimpleLogger::get_instance();
        DebugLevel global = logger.get_debug_level();

        if (logger.has_option(DebugOutputOption::ENABLE_AUTOLOG)) {
            enabled_ = true;
        } else {
            enabled_ = (global >= DebugLevel::DEBUG_LEVEL_DEBUG)
                       && (logger.has_option(DebugOutputOption::SHOW_FUNCNAME)
                           || logger.has_option(DebugOutputOption::SHOW_LINE));
        }

        if (enabled_) {
            params_ = args_to_string_(std::forward< Args >(args)...);
            emit_("begin");
        }
    }

    ~AutoLogger()
    {
        if (enabled_) {
            if (!oss_.str().empty()) emit_("stream: " + oss_.str());
            emit_("end");
        }
    }

    template < typename T > AutoLogger& operator<<(const T& v)
    {
        if (enabled_) oss_ << v;
        return *this;
    }

private:
    static std::string args_to_string_() { return ""; }
    template < typename First, typename... Rest >
    static std::string args_to_string_(const First& f, const Rest&... r)
    {
        std::ostringstream oss;
        oss << f;
        int dummy[] = { 0, (void(oss << ", " << r), 0)... };
        (void)dummy;
        return oss.str();
    }

    void emit_(const std::string& phase) const
    {
        auto&       logger      = SimpleLogger::get_instance();
        const char* phase_color = SIMPLE_LOG_WHITE_COLOR;
        if (phase == "begin") {
            phase_color = SIMPLE_LOG_GREEN_COLOR;
        } else if (phase == "end") {
            phase_color = SIMPLE_LOG_CYAN_COLOR;
        } else if (phase.find("stream:") == 0) {
            phase_color = SIMPLE_LOG_YELLOW_COLOR;
        }

        std::string core_tag =
            std::string(phase_color) + "[AutoLog] " + phase + SIMPLE_LOG_RESET_COLOR;

        std::string prefix   = logger.emit_prefix_(core_tag, file_, func_, line_);
        std::string log_line = prefix;

        if (!params_.empty()) {
            log_line += " | Params: " + params_;
        }

        std::cout << log_line << std::endl;

        if (logger.has_option(DebugOutputOption::ENABLE_FILE_LOG)) {
            logger.write_to_file(log_line);
        }
    }

    std::string        file_, func_, params_;
    int                line_;
    std::ostringstream oss_;
    bool               enabled_{ false };
};

}  // namespace simple_log

// —— 等级控制宏
#define SIMPLE_LOG_SET_LEVEL(lv) simple_log::SimpleLogger::get_instance().set_debug_level(lv)
#define SIMPLE_LOG_INIT_LEVEL_DEBUG() \
    SIMPLE_LOG_SET_LEVEL(simple_log::DebugLevel::DEBUG_LEVEL_DEBUG)
#define SIMPLE_LOG_INIT_LEVEL_INFO() SIMPLE_LOG_SET_LEVEL(simple_log::DebugLevel::DEBUG_LEVEL_INFO)
#define SIMPLE_LOG_INIT_LEVEL_WARN() SIMPLE_LOG_SET_LEVEL(simple_log::DebugLevel::DEBUG_LEVEL_WARN)
#define SIMPLE_LOG_INIT_LEVEL_ERROR() \
    SIMPLE_LOG_SET_LEVEL(simple_log::DebugLevel::DEBUG_LEVEL_ERROR)
#define SIMPLE_LOG_INIT_LEVEL_NONE() SIMPLE_LOG_SET_LEVEL(simple_log::DebugLevel::DEBUG_LEVEL_NONE)

// —— 选项控制宏
#define SIMPLE_LOG_SET_OPTION(opt, on) \
    simple_log::SimpleLogger::get_instance().set_output_option(opt, on)
#define SIMPLE_LOG_THREAD_ID(on) \
    SIMPLE_LOG_SET_OPTION(simple_log::DebugOutputOption::SHOW_THREAD_ID, on)
#define SIMPLE_LOG_SHOW_MILLIS(on) \
    SIMPLE_LOG_SET_OPTION(simple_log::DebugOutputOption::TIMESTAMP_MILLIS, on)
#define SIMPLE_LOG_ENABLE_AUTOLOG(on) \
    SIMPLE_LOG_SET_OPTION(simple_log::DebugOutputOption::ENABLE_AUTOLOG, on)
#define SIMPLE_LOG_ENABLE_FILE_LOG(on) \
    SIMPLE_LOG_SET_OPTION(simple_log::DebugOutputOption::ENABLE_FILE_LOG, on)
#define SIMPLE_LOG_SET_FILE(filepath, retention_days, enable_cleanup) \
    simple_log::SimpleLogger::get_instance().set_log_file(filepath, retention_days, enable_cleanup)
#define SIMPLE_LOG_ENABLE_AUTO_CLEANUP(on) \
    SIMPLE_LOG_SET_OPTION(simple_log::DebugOutputOption::ENABLE_AUTO_CLEANUP, on)

// ===== 一键配置宏（简化设置） =====
// 开发环境：启用文件日志，自动清理，保留7天
#define SIMPLE_LOG_INIT_DEV(level)        \
    do {                                  \
        SIMPLE_LOG_INIT_LEVEL_##level();  \
        SIMPLE_LOG_INIT_OPTION_DEFAULT(); \
        SIMPLE_LOG_SET_FILE("", 7, true); \
        SIMPLE_LOG_ENABLE_FILE_LOG(true); \
    } while (0)

// 生产环境：启用文件日志，自动清理，保留30天（一个月）的日志
#define SIMPLE_LOG_INIT_PROD(level)        \
    do {                                   \
        SIMPLE_LOG_INIT_LEVEL_##level();   \
        SIMPLE_LOG_INIT_OPTION_DEFAULT();  \
        SIMPLE_LOG_SET_FILE("", 30, true); \
        SIMPLE_LOG_ENABLE_FILE_LOG(true);  \
    } while (0)

// 仅控制台输出（不启用文件日志）
#define SIMPLE_LOG_INIT_CONSOLE(level)     \
    do {                                   \
        SIMPLE_LOG_INIT_LEVEL_##level();   \
        SIMPLE_LOG_INIT_OPTION_DEFAULT();  \
        SIMPLE_LOG_ENABLE_FILE_LOG(false); \
    } while (0)

// 自定义配置：等级、文件路径、保留天数、是否自动清理
#define SIMPLE_LOG_INIT_CUSTOM(level, filepath, retention_days, enable_cleanup) \
    do {                                                                        \
        SIMPLE_LOG_INIT_LEVEL_##level();                                        \
        SIMPLE_LOG_INIT_OPTION_DEFAULT();                                       \
        SIMPLE_LOG_SET_FILE(filepath, retention_days, enable_cleanup);          \
        SIMPLE_LOG_ENABLE_FILE_LOG(true);                                       \
    } while (0)

// —— 预设样式宏
#define SIMPLE_LOG_INIT_OPTION_DEFAULT()                                              \
    do {                                                                              \
        auto& lg = simple_log::SimpleLogger::get_instance();                          \
        lg.set_output_option(simple_log::DebugOutputOption::SHOW_TIMESTAMP, false);   \
        lg.set_output_option(simple_log::DebugOutputOption::TIMESTAMP_MILLIS, false); \
        lg.set_output_option(simple_log::DebugOutputOption::SHOW_LEVEL_FULL, true);   \
        lg.set_output_option(simple_log::DebugOutputOption::SHOW_THREAD_ID, false);   \
        lg.set_output_option(simple_log::DebugOutputOption::SHOW_FILENAME, true);     \
        lg.set_output_option(simple_log::DebugOutputOption::SHOW_FUNCNAME, true);     \
        lg.set_output_option(simple_log::DebugOutputOption::SHOW_LINE, true);         \
    } while (0)

#define SIMPLE_LOG_INIT_OPTION_ALL()                                                 \
    do {                                                                             \
        auto& lg = simple_log::SimpleLogger::get_instance();                         \
        lg.set_output_option(simple_log::DebugOutputOption::SHOW_TIMESTAMP, true);   \
        lg.set_output_option(simple_log::DebugOutputOption::TIMESTAMP_MILLIS, true); \
        lg.set_output_option(simple_log::DebugOutputOption::SHOW_LEVEL_FULL, true);  \
        lg.set_output_option(simple_log::DebugOutputOption::SHOW_THREAD_ID, true);   \
        lg.set_output_option(simple_log::DebugOutputOption::SHOW_FILENAME, true);    \
        lg.set_output_option(simple_log::DebugOutputOption::SHOW_FUNCNAME, true);    \
        lg.set_output_option(simple_log::DebugOutputOption::SHOW_LINE, true);        \
    } while (0)

#define SIMPLE_LOG_INIT_OPTION_MINIMAL()                                              \
    do {                                                                              \
        auto& lg = simple_log::SimpleLogger::get_instance();                          \
        lg.set_output_option(simple_log::DebugOutputOption::SHOW_TIMESTAMP, false);   \
        lg.set_output_option(simple_log::DebugOutputOption::TIMESTAMP_MILLIS, false); \
        lg.set_output_option(simple_log::DebugOutputOption::SHOW_LEVEL_FULL, true);   \
        lg.set_output_option(simple_log::DebugOutputOption::SHOW_THREAD_ID, false);   \
        lg.set_output_option(simple_log::DebugOutputOption::SHOW_FILENAME, false);    \
        lg.set_output_option(simple_log::DebugOutputOption::SHOW_FUNCNAME, false);    \
        lg.set_output_option(simple_log::DebugOutputOption::SHOW_LINE, false);        \
    } while (0)

#define SIMPLE_LOG_INIT_OPTION_FILE_LINE()                                            \
    do {                                                                              \
        auto& lg = simple_log::SimpleLogger::get_instance();                          \
        lg.set_output_option(simple_log::DebugOutputOption::SHOW_TIMESTAMP, true);    \
        lg.set_output_option(simple_log::DebugOutputOption::TIMESTAMP_MILLIS, false); \
        lg.set_output_option(simple_log::DebugOutputOption::SHOW_LEVEL_FULL, true);   \
        lg.set_output_option(simple_log::DebugOutputOption::SHOW_THREAD_ID, false);   \
        lg.set_output_option(simple_log::DebugOutputOption::SHOW_FILENAME, true);     \
        lg.set_output_option(simple_log::DebugOutputOption::SHOW_FUNCNAME, false);    \
        lg.set_output_option(simple_log::DebugOutputOption::SHOW_LINE, true);         \
    } while (0)

// —— 只启用 AutoLogger 的预设配置（用于学习代码执行流程）
// 注意：此配置会自动将日志级别设置为 NONE，禁用所有普通日志输出
#define SIMPLE_LOG_INIT_OPTION_AUTOLOG_ONLY()                                         \
    do {                                                                              \
        auto& lg = simple_log::SimpleLogger::get_instance();                          \
        lg.set_debug_level(simple_log::DebugLevel::DEBUG_LEVEL_NONE);                 \
        lg.set_output_option(simple_log::DebugOutputOption::SHOW_TIMESTAMP, true);    \
        lg.set_output_option(simple_log::DebugOutputOption::TIMESTAMP_MILLIS, false); \
        lg.set_output_option(simple_log::DebugOutputOption::SHOW_LEVEL_FULL, true);   \
        lg.set_output_option(simple_log::DebugOutputOption::SHOW_THREAD_ID, false);   \
        lg.set_output_option(simple_log::DebugOutputOption::SHOW_FILENAME, true);     \
        lg.set_output_option(simple_log::DebugOutputOption::SHOW_FUNCNAME, true);     \
        lg.set_output_option(simple_log::DebugOutputOption::SHOW_LINE, true);         \
        lg.set_output_option(simple_log::DebugOutputOption::ENABLE_AUTOLOG, true);    \
    } while (0)

// —— 日志输出宏
#define SIMPLE_LOG_ERROR                                                                     \
    simple_log::LogStream(simple_log::DebugLevel::DEBUG_LEVEL_ERROR, __FILE__, __FUNCTION__, \
                          __LINE__)
#define SIMPLE_LOG_WARNING                                                                  \
    simple_log::LogStream(simple_log::DebugLevel::DEBUG_LEVEL_WARN, __FILE__, __FUNCTION__, \
                          __LINE__)
#define SIMPLE_LOG_INFO                                                                     \
    simple_log::LogStream(simple_log::DebugLevel::DEBUG_LEVEL_INFO, __FILE__, __FUNCTION__, \
                          __LINE__)
#define SIMPLE_LOG_DEBUG                                                                     \
    simple_log::LogStream(simple_log::DebugLevel::DEBUG_LEVEL_DEBUG, __FILE__, __FUNCTION__, \
                          __LINE__)

// —— 条件日志宏
#define SIMPLE_LOG_ERROR_IF(cond)                                                            \
    simple_log::LogStream(simple_log::DebugLevel::DEBUG_LEVEL_ERROR, __FILE__, __FUNCTION__, \
                          __LINE__, cond)
#define SIMPLE_LOG_WARNING_IF(cond)                                                         \
    simple_log::LogStream(simple_log::DebugLevel::DEBUG_LEVEL_WARN, __FILE__, __FUNCTION__, \
                          __LINE__, cond)
#define SIMPLE_LOG_INFO_IF(cond)                                                            \
    simple_log::LogStream(simple_log::DebugLevel::DEBUG_LEVEL_INFO, __FILE__, __FUNCTION__, \
                          __LINE__, cond)
#define SIMPLE_LOG_DEBUG_IF(cond)                                                            \
    simple_log::LogStream(simple_log::DebugLevel::DEBUG_LEVEL_DEBUG, __FILE__, __FUNCTION__, \
                          __LINE__, cond)

#define SIMPLE_AUTO_LOGGER() \
    simple_log::AutoLogger autoLogger(__FILE__, __FUNCTION__, __LINE__)
// 带参数版本
#define SIMPLE_AUTO_LOGGER_ARGS(...) \
    simple_log::AutoLogger autoLogger(__FILE__, __FUNCTION__, __LINE__, __VA_ARGS__)

#endif  // SIMPLE_LOG_H

/**
使用示例
#include "simple_log.h"

int main(void)
{
    SIMPLE_LOG_INIT_LEVEL_DEBUG(); //设置 log等级
    SIMPLE_LOG_INIT_OPTION_DEFAULT();//设置输出内容

    // 无参数版本
    SIMPLE_AUTO_LOGGER();

    // 带参数版本
    SIMPLE_AUTO_LOGGER_ARGS("param1", 123, "param2");

    // SIMPLE_LOG_SET_OPTION(simple_log::DebugOutputOption::SHOW_FUNCNAME,
false);//关闭 输出函数
    // SIMPLE_LOG_SET_OPTION(simple_log::DebugOutputOption::SHOW_LINE,
ture);//输出显示行
    //  simple_log::DebugOutputOption::SHOW_LINE

    SIMPLE_LOG_ERROR << "1" << 2;
    SIMPLE_LOG_WARNING << "2";
}

// 只启用 AutoLogger 的示例（用于学习代码执行流程）
void example_autolog_only()
{
    // 设置日志级别为 NONE，禁用所有普通日志输出
    SIMPLE_LOG_INIT_LEVEL_NONE();
    // 只启用 AutoLogger，这样只会输出函数进入/退出信息
    SIMPLE_LOG_INIT_OPTION_AUTOLOG_ONLY();

    // 现在只有 SIMPLE_AUTO_LOGGER() 会输出
    SIMPLE_AUTO_LOGGER();
    // 这些都不会输出（因为级别是 NONE）
    // SIMPLE_LOG_ERROR << "test";
    // SIMPLE_LOG_WARNING << "test";
    // SIMPLE_LOG_INFO << "test";
    // SIMPLE_LOG_DEBUG << "test";
}

// 启用文件日志的示例
void example_file_log()
{
    // 方式1：开发环境（推荐）
    SIMPLE_LOG_INIT_DEV(DEBUG);  // 保留7天，自动清理，超过1MB自动切换文件

    // 方式2：生产环境（推荐）
    // SIMPLE_LOG_INIT_PROD(DEBUG);  //
保留30天（一个月），自动清理，超过1MB自动切换文件

    // 方式3：自定义配置
    // SIMPLE_LOG_INIT_CUSTOM(DEBUG, "", 30, true);  //
等级、路径、保留天数、是否清理

    // 日志会自动写入文件，文件名格式：app_YYYYMMDD_HHMMSS.log
    //
当文件超过1MB时，会自动创建新文件：app_YYYYMMDD_HHMMSS_1.log、app_YYYYMMDD_HHMMSS_2.log
等
    // 启动时会自动删除超过保留天数的旧日志文件
    SIMPLE_LOG_INFO << "这条日志会同时输出到控制台和文件";
    SIMPLE_AUTO_LOGGER();
}
*/